
#include "grb_control.h"
#include "zy_can.h"
#include "gqueue.h"

extern gqueue_t qCan2Rcv;

#define GRB_PANEL_CHANNEL               0
#define GRB_FRONT_STRIP_CHANNEL         1
#define GRB_REAR_STRIP_CHANNEL          2
#define WHEEL_STRIP_CHANNEL             4

#define SCROLL_STEP                     2       // 每次滚动的灯珠数量
#define SCROLL_MAX_TIME                 2000

#define CMD_CAN_ID(ch,e)    (0x600 | (ch << 4) | (e))

#define WHEEL_EFFECT_COUNT              6       // 0,1,2,3,4,5
#define WHEEL_EFFECT_DIVIDE             20      // 20*5=100

#define FRONT_BACK_STRIP_STATE_IDLE     0
#define FRONT_BACK_STRIP_STATE_SEND     1
#define FRONT_BACK_STRIP_STATE_REPLY    2



static int state_front_back_strip_control = 0;
static uint8_t frontBackEffectIndex,frontBackScrollNum,frontBackPeriod;
const grb_scroll_param_t wheelScroll[WHEEL_EFFECT_COUNT] =
{
        {0,3},
        {1,3},
        {2,2},
        {3,2},
        {4,1},
        {5,1},
};

static void grb_scroll_control(grb_control_t ctrl,uint8_t scrollNum,uint8_t period)
{
    can_message_t msg;
    msg.ide = 0;
    msg.rtr = 0;
    msg.id = CMD_CAN_ID(ctrl.ch,ctrl.effectIndex);
    msg.len = 3;
    msg.data[0] = SCROLL;
    msg.data[1] = scrollNum;
    msg.data[2] = period;
    CanTransmit(2, &msg);
}

static void grb_breathe_control(grb_control_t ctrl,uint8_t breatheNum,uint8_t period)
{
    can_message_t msg;
    msg.ide = 0;
    msg.rtr = 0;
    msg.id = CMD_CAN_ID(ctrl.ch,ctrl.effectIndex);
    msg.len = 3;
    msg.data[0] = BREATHE;
    msg.data[1] = breatheNum;
    msg.data[2] = period;
    CanTransmit(2, &msg);
}

static void grb_character_control(grb_control_t ctrl,uint32_t grbColor,uint8_t* characters)
{
    can_message_t msg;
    msg.ide = 0;
    msg.rtr = 0;
    msg.id = CMD_CAN_ID(ctrl.ch,ctrl.effectIndex);
    msg.len = 6;
    msg.data[0] = CHARACTER;
    msg.data[1] = (grbColor>>16)&0xFF;
    msg.data[2] = (grbColor>>8)&0xFF;
    msg.data[3] = grbColor&0xFF;
    msg.data[4] = *characters;
    msg.data[5] = *(characters+1);
    CanTransmit(2, &msg);
}

static void grb_image_control(grb_control_t ctrl,uint32_t grbColor)
{
    can_message_t msg;
    msg.ide = 0;
    msg.rtr = 0;
    msg.id = CMD_CAN_ID(ctrl.ch,ctrl.effectIndex);
    msg.len = 4;
    msg.data[0] = IMAGE;
    msg.data[1] = (grbColor>>16)&0xFF;
    msg.data[2] = (grbColor>>8)&0xFF;
    msg.data[3] = grbColor&0xFF;
    CanTransmit(2, &msg);
}

static void car_front_back_strip(void)
{
    grb_control_t ctrl;
    ctrl.ch = GRB_FRONT_STRIP_CHANNEL;
    ctrl.effectIndex = frontBackEffectIndex;
    grb_scroll_control(ctrl,frontBackScrollNum,frontBackPeriod);

    ctrl.ch = GRB_REAR_STRIP_CHANNEL;
    grb_scroll_control(ctrl,frontBackScrollNum,frontBackPeriod);
}

void car_speed_control(uint8_t speed)
{
    uint8_t scrollNum = 0;
    uint8_t period = 0;
    grb_control_t ctrl;

    ctrl.ch = WHEEL_STRIP_CHANNEL;
    ctrl.effectIndex = 0;

    if(speed > 0){
        // 将0-100的速度转换成滚动周期
        if(speed > 100){
            speed = 100;
        }
        uint8_t paramIndex = speed/WHEEL_EFFECT_DIVIDE;
        period = SCROLL_MAX_TIME/speed;
        scrollNum = wheelScroll[paramIndex].scrollSteps;
        ctrl.effectIndex = wheelScroll[paramIndex].effectIndex;
    }
    grb_scroll_control(ctrl,scrollNum,period);

}

void grb_panel_control(xd_grb_panel_t panel)
{
    uint32_t grb = 0;
    grb_control_t ctrl;
    ctrl.ch = GRB_PANEL_CHANNEL;
    grb = (panel.g<<16) | (panel.r<<8) | (panel.b&0xFF);
    if(panel.c1 == 0){
        ctrl.effectIndex = panel.c2;
        grb_image_control(ctrl,grb);
    }else{
        ctrl.effectIndex = 0xF;
        uint8_t character[2] = {0};
        character[0] = panel.c1;
        character[1] = panel.c2;
        grb_character_control(ctrl,grb,character);
    }
}

void car_front_back_strip_control(uint8_t effectIndex,uint8_t scrollNum,uint8_t period)
{
    frontBackEffectIndex = effectIndex;
    frontBackScrollNum = scrollNum;
    frontBackPeriod = period;
    state_front_back_strip_control = FRONT_BACK_STRIP_STATE_SEND;
}


/*
 * @brief 灯带控制的指令发送，并检测回复
 */
void car_strip_process(void)
{
#define STATE_IDLE  0
#define STATE_SEND  1
#define STATE_REPLY 2
    can_message_t msgReply;
    switch(state_front_back_strip_control){
    case FRONT_BACK_STRIP_STATE_IDLE:
        if(gqueue_is_empty(&qCan2Rcv) == 0){    // 队列里有数据
            gqueue_clear(&qCan2Rcv);
        }
        break;
    case FRONT_BACK_STRIP_STATE_SEND:
        car_front_back_strip();
        state_front_back_strip_control = FRONT_BACK_STRIP_STATE_REPLY;
        break;
    case FRONT_BACK_STRIP_STATE_REPLY:
        if(gqueue_pop(&qCan2Rcv, &msgReply) == 0){
            if(((msgReply.id>>4) & 0x0F) == GRB_FRONT_STRIP_CHANNEL ||
               ((msgReply.id>>4) & 0x0F) == GRB_REAR_STRIP_CHANNEL ){
                state_front_back_strip_control = FRONT_BACK_STRIP_STATE_IDLE;
            }else{  // 收到的回复不对
                car_front_back_strip();
            }
        }else{      // 重发
            car_front_back_strip();
        }
        break;
    }

}


